# -*- coding: iso-8859-2 -*-

import math

from authorshipanalyzer.file import ResourceReader
from authorshipanalyzer.slot import Slot
from authorshipanalyzer.utils import getKey

class CategoryFiller:
    '''
    Fill slots with categories and subjects
    '''
    
    def __init__(self, keyWordsDirs = [ "categories", "subjects" ]):
        '''
        Create categories vectors
        @param categoriesWords: dict<category_name, list_of_category_words>
        @param weights: dict<category_word, wieght> 
        '''
        self.categoriesWords = {}
        
        reader = ResourceReader()
        for dir in keyWordsDirs:
            categoryNames = reader.getMechanizmFilesDict(dir)
            for category in categoryNames.keys():
                categoryWords = reader.readWordList(categoryNames[category])
                self.categoriesWords[category] = categoryWords
        
        # initially wall weights are set to zeros, keys are all words from all categories
        self.weights = {}        
        for key, value in self.categoriesWords.items():
            for word in value:
                self.weights[word] = 0.0
            
    def createCategories(self, slots):
        '''
        @param slots: list of slots filled with word frequency dictionary
        '''
        # Count the number of documents where occours at least one term (df)
        for slot in slots:
            counted = []    # as we count documents not occourences
            for word, freq in slot.wordFrequency.items():
                word = getKey(self.weights, word)
                if word != None and word not in counted:
                    self.weights[word] += 1.0
                    counted.append(word)
                 
        # number of all documents   
        N = float(len(slots))
                  
        for word, weight in self.weights.items():
            # if word do not occours in any of the message, get rid of it
            if weight == 0:
                del self.weights[word]
                continue
            
            # count weight otherwise log(df/N)
            self.weights[word] = math.log(N / weight)         
        
        ####################################################
        # Words weights
        
        for key, words in self.categoriesWords.items():
            print "--------> cat: " + key
            file = open("/tmp/" + key + ".txt", "w")
            for word in words:
                if self.weights.has_key(word):
                    print word + " " + str(self.weights[word])
                    file.write(word + " " + str(self.weights[word]) + "\n")
                else:
                    print word + " 0.0"
                    file.write(word + " 0.0\n")
            file.close()
                
        from sys import exit
        exit(0)
        
        ####################################################
                
        self.categories = {}
        # for each word which is a category word an occours in documents
        for word in self.weights.keys():
            # foreach category create category dict
            for category, words in self.categoriesWords.items():
                if not self.categories.has_key(category):
                    self.categories[category] = {}
                if word in words:
                    self.categories[category][word] = 1.0
                else:
                    self.categories[category][word] = 0.0
        
        # Normalize category vectors
        for category, words in self.categories.items():
            sum = 0.0
            for word, freq in words.items():
                sum += freq
            if sum > 0.0:
                for word, freq in words.items():
                    self.categories[category][word] = freq / sum    
            
            print category
            print self.categories[category]
    
    def categorize(self, slots):
        '''
        @param slots: list of slots filled with word frequency dictionary
        '''
        for slot in slots:
            # create slot vector <word, tf*log(td/N)>
            slotVector = {}
            slotTextLen = 0.0
            for word, weight in self.weights.items():
                key = getKey(slot.wordFrequency, word) 
                if key != None: 
                    slotVector[word] = slot.wordFrequency[word] * weight
                    slotTextLen += slot.wordFrequency[word]
                    print "!!! Found term: " + word
                else:
                    slotVector[word] = 0.0
                    
            # normalize vector
            if slotTextLen > 0.0:
                for word, weight in slotVector.items():
                    slotVector[word] = weight / slotTextLen
            
            # <category, cosinus value>        
            results = {} 
            
            # foreach category count cosinus
            for category, words in self.categories.items():
                
                cosinus = 0.0
                slotDenominator = 0.0
                catDenominator = 0.0
                
                for word, occ in self.categories[category].items():
                    cosinus += self.categories[category][word] * slotVector[word]
                    slotDenominator += slotVector[word] * slotVector[word]
                    catDenominator += self.categories[category][word] * self.categories[category][word]
                    
                denominator = math.sqrt(slotDenominator) * math.sqrt(catDenominator)
                if denominator > 0.0:
                    cosinus /= math.sqrt(slotDenominator) * math.sqrt(catDenominator)
                else:
                    cosinus = 0.0
                results[category] = abs(cosinus)

            print slot.text
            max = 0.0
            category = None
            for cat, cos in results.items():
                print cat + " --> " + str(cos)
                if cos > max:
                    max = cos
                    category = cat
            
            if max > 0.1:        
                print category + " -------> " + str(max)   
                slot.category = category
                
            
if __name__ == "__main__":
    cf = CategoryFiller()
    
    import datetime
    import os
    from time import time
    
    from authorshipanalyzer.message import Message
    from authorshipanalyzer.message import MessageReader
    from authorshipanalyzer.file import Path
    from authorshipanalyzer.textmodifier import MessagePreprocessor
    from authorshipanalyzer.slot import Slot
    from authorshipanalyzer.slot import SlotManager

    fromDate = datetime.date(1996, 1, 1)
    toDate = datetime.date(2009, 5, 3)
    
    start = time()
    mr = MessageReader(Path.getMainDir() + os.sep + "info1")
    messages = mr.readMessages(fromDate, toDate)
    end = time()
    print "Retrieving " + str(len(messages)) + " messages: " + str(end - start) + " seconds"

    start = time()
    sm = SlotManager()
    sm.createSlots(messages)
    end = time()
    
    print "Creating slots: " + str(end - start) + " seconds"
    print "Number of messages:", str(len(messages))
    
    cf.createCategories(sm.slots)
#    cf.categorize(sm.slots)